package cn.tedu.mall.seckill.service.impl;

import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import cn.tedu.mall.pojo.seckill.vo.SeckillCommitVO;
import cn.tedu.mall.seckill.interceptor.SeckillInterceptor;
import cn.tedu.mall.seckill.service.ISeckillService;
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class SeckillCommitServiceImpl implements ISeckillService {
    /**
     * 在方法中执行的业务逻辑
     * 1.randCode 是否是当初初始化预热对应这个spu生成的randCode验证
     * 发送一个消息到订单新增的队列中,由订单系统消费者,实现异步下单
     * 2.防止同一个用户,抢购下单同一个skuId多次
     * 3.执行redis减库存验证,返回值不是负数就验证通过
     * 最终发送异步消息
     *
     * @param seckillOrderAddDTO
     * @return
     */
    @Autowired
    private RedisTemplate redisTemplate;
    //严格按照order顺序 排列的
    //先验证随机字符串,再验证重复秒杀,最后减库存
    @Autowired
    private List<SeckillInterceptor> seckillInterceptors;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public SeckillCommitVO commitSeckill(SeckillOrderAddDTO seckillOrderAddDTO) {
        //执行拦截验证,通过刚才封装返回数据,发送异步消息
        check(seckillOrderAddDTO);
        //准备消息String msg json字符串
        String msg = JSON.toJSONString(seckillOrderAddDTO);
        //发送消息 为了复用消费逻辑,直接往order系统的队列主题里发送,tag携带seckillAdd
        SendResult sendResult = rocketMQTemplate.syncSend
                ("csmall-order-add-topic:seckillAdd", msg);
        //根据send结果,返回数据
        if (sendResult.getSendStatus().toString().equals("SEND_OK")) {
            SeckillCommitVO seckillCommitVO = new SeckillCommitVO();
            seckillCommitVO.setSn(seckillOrderAddDTO.getSn());
            seckillCommitVO.setCreateTime(LocalDateTime.now());
            return seckillCommitVO;
        }
        return null;
    }

    private void check(SeckillOrderAddDTO seckillOrderAddDTO) {
        //循环拦截器,依次调用check方法
        for (SeckillInterceptor seckillInterceptor : seckillInterceptors) {
            seckillInterceptor.seckillCommitCheck(seckillOrderAddDTO);
        }
    }
}
